import logging
import time
import copy
import ast
from datetime import timedelta, datetime
import requests
import json
from redis import StrictRedis
from django.conf import settings
from common.mg_core import mg
from event_rule.dwc.qk_marketing_rule.dwc_daily_chn_report import DAILY_CHN_REPORT
from event_rule.dwc.qk_marketing_rule.daily_user_info import USER_INFO_REPORT
from common.es_core.report_creator import (
    ReportCreator,
    get_key_mapper_list,
    add_attachment_to_report_config
)
from common.es_core.es_interface import es_search_interface
from preprocessor.dwc.model_router import ACCOUNT_MODEL_ROUTER
from common.account.db import get_user
from common.es_core.user_filter import UserFilter
from common.dwc import shared_handler
from event_rule.dwc.attachment.channel_tax_attachment import CHANNEL_TAX_ATTACHMENT

_LOGGER = logging.getLogger(__name__)

redis = StrictRedis.from_url(settings.GENERAL_REDIS, charset="utf-8", decode_responses=True)


def _get_daily_chn_report_dynamic_target_users_dct(index, start_time, end_time):
    user_filter = UserFilter(merchant_name=index)
    user_filter.event_user_filter(['recharge'], start_time, end_time)
    recharge_user = user_filter.get_user_pool()
    user_filter = UserFilter(merchant_name=index, user_pool=recharge_user)
    user_filter.stage_filter(['recharge'], 'recharge_price', 'value_count',
                             start_time - timedelta(days=3650), start_time, 0, None)
    recharged_user = user_filter.get_user_pool()
    first_recharge_user = list(set(recharge_user) - set(recharged_user))
    first_recharge_query_dsl = {
        "query": {
            "bool": {
                "filter": [
                    {"term": {"_event_id": "recharge"}},
                    {"terms": {"_user_id": first_recharge_user}},
                    {"range": {"_event_time": {"gte": start_time.timestamp(), "lt": end_time.timestamp()}}}
                ]
            }
        },
        "size": 10000,
        "sort": [
            {"_event_time": {"order": "asc"}}
        ]
    }
    res = es_search_interface(index, first_recharge_query_dsl)
    first_recharge_out_trans_id, user_pool = [], []
    for recharge in res.get('hits', {}).get('hits', []):
        if recharge['_source']['_user_id'] in user_pool:
            continue
        first_recharge_out_trans_id.append(recharge['_source']['recharge_out_trans_id'])
        user_pool.append(recharge['_source']['_user_id'])
    dynamic_target_users_dct = dict(
        first_recharge_user_pool=user_pool,
        first_recharge_out_trans_id=first_recharge_out_trans_id,
    )
    return dynamic_target_users_dct


def _get_ios_chn_report(index, start_time, end_time, dynamic_argument_dct):
    ios_daily_chn_report_event_rule = copy.deepcopy(DAILY_CHN_REPORT)
    ios_daily_chn_report_event_rule['group_by'] = '_qk_appid.keyword'
    ios_daily_report = ReportCreator.create_report(start_time=start_time, end_time=end_time,
                                                   event_rule=ios_daily_chn_report_event_rule, index=index,
                                                   custom_filter=[{"exists": {"field": "_qk_appid"}}],
                                                   dynamic_argument_dct=dynamic_argument_dct, to_group=True)
    ios_daily_report['list'] = [dict(('_chn', v) if k == '_qk_appid' else (k, v)
                                     for k, v in report.items()) for report in ios_daily_report['list']]
    for ios_report in ios_daily_report['list']:
        ios_report['app_id_stats'] = 1
    return ios_daily_report


def _merge_daily_chn_report(original_result, app_id_result):
    key_to_merge = ['register_count', 'bind_count', 'first_recharge_user', 'first_recharge_count', 'recharge_new_user',
                    'recharge_new_amount', 'recharge_amount', 'recharge_user', 'online_recharge', 'agency_recharge',
                    'withdraw_amount', 'true_profit', 'tax_amount', 'high_level_fish_bet_amount', 'channel_tax_amount']
    original_result_map = {report['_chn']: report for report in original_result}
    app_id_result_map = {report['_chn']: report for report in app_id_result}
    for channel, report in app_id_result_map.items():
        if channel in original_result_map:
            for report_key, value in original_result_map[channel].items():
                if report_key not in key_to_merge:
                    continue
                original_result_map[channel][report_key] += report[report_key]
        else:
            original_result_map[channel] = report
    original_result = [report for report in original_result_map.values()]
    return original_result


def get_daily_chn_report(index, start_time, end_time):
    dynamic_argument_dct = _get_daily_chn_report_dynamic_target_users_dct(index, start_time, end_time)
    daily_report = ReportCreator.create_report(start_time=start_time, end_time=end_time,
                                               event_rule=DAILY_CHN_REPORT, index=index,
                                               dynamic_argument_dct=dynamic_argument_dct, to_group=True)
    ios_daily_report = _get_ios_chn_report(index, start_time, end_time, dynamic_argument_dct)
    daily_report['list'] = _merge_daily_chn_report(daily_report['list'], ios_daily_report['list'])
    daily_report['total_count'] = len(daily_report['list'])
    key_mapper = get_key_mapper_list(DAILY_CHN_REPORT.get("values"))
    return dict(list=daily_report['list'], key_mapper=key_mapper, total_count=daily_report['total_count'])


def get_user_info(timestamp):
    now_ts = time.time()
    results, total_count = mg.get_report('qk', 'market_user_info', {"timestamp": {"$gte": timestamp}}, sort_key='user_id',
                                         page=1, size=20, disable_paginate=True, export_size_limit=30000)
    return dict(not_ts=now_ts, user_info=list(results))


def get_qk_chn_list():
    res = requests.get(url=settings.QK_CHANNEL_LIST_API)
    res_json = json.loads(res.content)
    chn_list = res_json['data']
    return chn_list


def create_qk_user_info(index, user_pool=None, start_time=None, end_time=None, max_size=10000):
    chn_list = get_qk_chn_list()
    day_start_time = start_time if start_time else datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
    day_end_time = end_time if end_time else day_start_time + timedelta(days=1)
    daily_report = ReportCreator.create_report(
        start_time=day_start_time, end_time=day_end_time,
        event_rule=add_attachment_to_report_config(USER_INFO_REPORT, CHANNEL_TAX_ATTACHMENT), index=index,
        custom_filter=[{"bool": {"should": [{"terms": {"_chn": chn_list}}, {"terms": {"_qk_appid": chn_list}}]}}],
        custom_not_filter=[{"term": {"_user_id": 1}}], user_pool=user_pool, max_bucket=max_size, to_group=True)
    user_pool = [user_info['_user_id'] for user_info in daily_report['list']]
    account_model = ACCOUNT_MODEL_ROUTER[index]
    users = account_model.objects.filter(**{'user_id__in': user_pool})
    user_map = {user.user_id: user for user in users}
    for report in daily_report['list']:
        if not user_map.get(report['_user_id']):
            continue
        user_ins = user_map[report['_user_id']]
        to_update = {
            '$set': {
                'index': index,
                'user_id': int(report['_user_id']),
                'recharge': report['recharge'],
                'tax': report['tax'],
                'profit': report['profit'],
                'channel_tax': report['channel_tax_amount'],
                'real_channel_tax': report['real_channel_tax_amount'],
                'channel': user_ins.qk_appid if user_ins.qk_appid else user_ins.channel,
                'registered_ip': user_ins.ip,
                'last_active_at': datetime.fromtimestamp(report['last_active_at']),
                'last_active_ts': report['last_active_at'],
                'platform': 'ios' if user_ins.channel.startswith('ios') else 'android',
                'balance': report['account_info'].get('_source', {}).get('user_data_sync_balance', 0),
                'safe_balance': report['account_info'].get('_source', {}).get('user_data_sync_safe_balance', 0),
                'timestamp': time.time(),
                'registered_at': user_ins.registered_at
            },
            '$setOnInsert': {
                'total_recharge': 0,
                'total_profit': 0,
                'total_tax': 0,
                'total_real_channel_tax': 0
            }
        }
        record = mg.MONGODB['qk']['market_user_info'].find_one({"_id": '-'.join([index, str(report['_user_id'])]),
                                                                "timestamp": {"$lt": day_start_time.timestamp()}})
        if record:
            mg.MONGODB['qk']['market_user_info'].update_one(
                {"_id": '-'.join([index, str(report['_user_id'])]),
                 "timestamp": {"$lt": day_start_time.timestamp()}},
                {"$inc": {"total_recharge": record['recharge'],
                          "total_tax": record['tax'],
                          "total_profit": record.get('profit', 0),
                          "total_channel_tax_amount": record.get('channel_tax', 0),
                          "total_real_channel_tax": record.get(
                          'real_channel_tax', 0)}}),
        mg.MONGODB['qk']['market_user_info'].update_one({'_id': '-'.join([index, str(report['_user_id'])])},
                                                        to_update, True)


def manual_bind_chn(platform_id, user_id, app_id):
    _LOGGER.info('qk manual bind user: starting bind user: {}'.format(user_id))
    shared_handler.manual_bind_appid(platform_id, user_id, shared_handler.MarketingPlatformType.QK, app_id)
    _LOGGER.info('qk manual bind user: user: {} bind'.format(user_id))
    user = get_user(platform_id, user_id)
    today_start = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
    # 以前註冊的用戶刷新數據
    if str(user['registered_at']) < str(today_start):
        qk_users_info = ast.literal_eval(redis.get("qk_user_info")) if redis.get("qk_user_info") else dict()
        start_time = int(user['registered_at'].timestamp())
        qk_users_info.update({user['user_id']: {"platform_id": platform_id, "start_time": start_time,
                                                "add_time": int(time.time())}})
        redis.set("qk_user_info", qk_users_info)
        _LOGGER.info('qk manual bind user: add user_id:{} into redis'.format(user['user_id']))


def get_user_channel_for_marketing_platform(platform_id, user_id):
    return shared_handler.get_user_channel_for_marketing_platform(
        platform_id, user_id, shared_handler.MarketingPlatformType.QK)


if __name__ == '__main__':
    start = datetime(2019, 3, 21)
    end = datetime(2019, 3, 22)
    print(get_daily_chn_report('dark3', start, end))
